package org.cjstudio.messageboard;

import java.util.ArrayList;

import org.cjstudio.messageboard.model.Message;

public class MessageCommands {

	public static class Parameters {
		public String key;
		public Message message;

		public Parameters(String key) {
			this.key = key;
		}

		public Parameters(String key, Message message) {
			this.key = key;
			this.message = message;
		}
	}

	public interface MessageCommand<ReturnType> {
		public void setParameters(Parameters params);
		public ReturnType execute();
		public Class<ReturnType> getReturyType();
		/* I don't know how I can utilize the return type of this command... */
	}

	public static final int OPCODE_NONE = 0;
	public static final int OPCODE_CREATE = 1;
	public static final int OPCODE_RETRIEVE = 2;
	public static final int OPCODE_UPDATE = 3;
	public static final int OPCODE_DELETE = 4;
	public static final int OPCODE_RETRIEVE_ALL = 5;

	public static final int getOpcodeFromString(String opcodeString) {
		if (opcodeString.equals("Create")) {
			return OPCODE_CREATE;
		} else if (opcodeString.equals("Retrieve")) {
			return OPCODE_RETRIEVE;
		} else if (opcodeString.equals("Update")) {
			return OPCODE_UPDATE;
		} else if (opcodeString.equals("Delete")) {
			return OPCODE_DELETE;
		}
		return OPCODE_NONE;
	}

	@SuppressWarnings("rawtypes")
	public static MessageCommand getCommand(int opcode) {
		switch (opcode) {
		case OPCODE_CREATE:
			return new CreateMessageEntry();
		case OPCODE_RETRIEVE:
			return new RetrieveMessageEntry();
		case OPCODE_UPDATE:
			return new UpdateMessageEntry();
		case OPCODE_DELETE:
			return new DeleteMessageEntry();
		case OPCODE_RETRIEVE_ALL:
			return new RetrieveAllMessageEntries();
		default:
			return null;
		}
	}

	public static class CreateMessageEntry implements MessageCommand<Boolean> {

		private MessageDAODatastoreImpl messageDAO;
		private String key;
		private Message message;

		public CreateMessageEntry() {
			this.messageDAO = MessageDAODatastoreImpl.getInstance();
		}

		@Override
		public void setParameters(Parameters params) {
			this.key = params.key;
			this.message = params.message;
		}

		@Override
		public Boolean execute() {
			return messageDAO.create(key, message);
		}

		@Override
		public Class<Boolean> getReturyType() {
			return Boolean.class;
		}
	}

	public static class RetrieveMessageEntry implements MessageCommand<Message> {

		private MessageDAODatastoreImpl messageDAO;
		private String key;

		public RetrieveMessageEntry() {
			this.messageDAO = MessageDAODatastoreImpl.getInstance();
		}

		@Override
		public void setParameters(Parameters params) {
			this.key = params.key;
		}

		@Override
		public Message execute() {
			return messageDAO.retrieve(key);
		}

		@Override
		public Class<Message> getReturyType() {
			return Message.class;
		}
	}

	public static class RetrieveAllMessageEntries implements
			MessageCommand<ArrayList<Message>> {

		private MessageDAODatastoreImpl messageDAO;

		public RetrieveAllMessageEntries() {
			this.messageDAO = MessageDAODatastoreImpl.getInstance();
		}

		@Override
		public void setParameters(Parameters params) {
		}

		@Override
		public ArrayList<Message> execute() {
			return messageDAO.retrieve();
		}

		@Override
		public Class<ArrayList<Message>> getReturyType() {
			return null; // how to do this...
		}
	}

	public static class UpdateMessageEntry implements MessageCommand<Boolean> {

		public static final Class<Boolean> ResultType = Boolean.class;

		private MessageDAODatastoreImpl messageDAO;
		private String key;
		private Message newMessage;

		public UpdateMessageEntry() {
			this.messageDAO = MessageDAODatastoreImpl.getInstance();
		}

		@Override
		public void setParameters(Parameters params) {
			this.key = params.key;
			this.newMessage = params.message;
		}

		@Override
		public Boolean execute() {
			return messageDAO.update(key, newMessage);
		}

		@Override
		public Class<Boolean> getReturyType() {
			return Boolean.class;
		}
	}

	public static class DeleteMessageEntry implements MessageCommand<Boolean> {

		public static final Class<Boolean> ResultType = Boolean.class;

		private MessageDAODatastoreImpl messageDAO;
		private String key;

		public DeleteMessageEntry() {
			this.messageDAO = MessageDAODatastoreImpl.getInstance();
		}

		@Override
		public void setParameters(Parameters params) {
			this.key = params.key;
		}

		@Override
		public Boolean execute() {
			return messageDAO.delete(key);
		}

		@Override
		public Class<Boolean> getReturyType() {
			return Boolean.class;
		}
	}
}
